PTA数据结构题目集 第五周——堆&哈夫曼树&并查集

发表于 2020-08-08 1166 字 6 min read

文章目录
cos's avatar

cos

FE / ACG / 手工 / 深色模式强迫症 / INFP / 兴趣广泛养两只猫的老宅女 / remote

暂无目录
剑指offer day31 数学(困难)剑指offer day30 分治算法(困难)剑指offer day29 动态规划(困难)剑指offer day28 搜索与回溯算法(困难)剑指offer day27 栈与队列(困难)剑指offer day26 字符串(中等)剑指offer day25 模拟(中等)剑指offer day24 数学(中等)剑指offer day23 数学(简单)剑指offer day22 位运算(中等)剑指offer day21 位运算(简单)剑指offer day20 分治算法(中等)剑指offer day19 搜索与回溯算法(中等)剑指offer day18 搜索与回溯算法(中等)剑指offer day17 排序(中等)剑指offer day16 排序(简单)剑指offer day15 搜索与回溯算法(中等)剑指offer day14 搜索与回溯算法(中等)剑指offer day13 双指针(简单)剑指offer day12 双指针(简单)剑指offer day11 双指针(简单)剑指offer day10 动态规划(中等)剑指offer day9 动态规划(中等)剑指offer day8 动态规划(简单)剑指offer day7 搜索与回溯算法(简单)剑指offer day6 搜索与回溯算法(简单)剑指offer day5 查找算法(中等)剑指offer day4 查找算法(简单)剑指offer day3 字符串(简单)剑指offer day2 链表(简单)剑指offer day1 栈与队列(简单)冲刺春招-精选笔面试66题大通关day22冲刺春招-精选笔面试66题大通关day21冲刺春招-精选笔面试66题大通关day20冲刺春招-精选笔面试66题大通关day19冲刺春招-精选笔面试66题大通关18冲刺春招-精选笔面试66题大通关17冲刺春招-精选笔面试66题大通关16冲刺春招-精选笔面试66题大通关day15冲刺春招-精选笔面试66题大通关day14冲刺春招-精选笔面试66题大通关day13冲刺春招-精选笔面试66题大通关day12冲刺春招-精选笔面试66题大通关day11冲刺春招-精选笔面试66题大通关day10冲刺春招-精选笔面试66题大通关day9冲刺春招-精选笔面试66题大通关day8冲刺春招-精选笔面试66题大通关day7冲刺春招-精选笔面试66题大通关day6冲刺春招-精选笔面试66题大通关day5冲刺春招-精选笔面试66题大通关day4冲刺春招-精选笔面试66题大通关day3冲刺春招-精选笔面试66题大通关day2冲刺春招-精选笔面试66题大通关day12021秋PAT乙级真题题解及赛后总结PAT乙级刷题感想及踩坑总结PTA数据结构题目集 第三周——栽树(二叉树等)PTA数据结构题目集 第十一周——散列查找PTA数据结构题目集 第十周——排序(下)PTA数据结构题目集 第九周——排序(上)PTA数据结构题目集 第八周——图(下)PTA数据结构题目集 第七周——图(中)PTA数据结构题目集 第六周——图(上)PTA数据结构题目集 第五周——堆&哈夫曼树&并查集PTA数据结构题目集 第四周——二叉搜索树&二叉平衡树PTA数据结构题目集 第二周——线性结构PTA数据结构题目集 第一周——最大子列和算法、二分查找MOOC浙大数据结构课后题记录——PTA数据结构题目集(全)2020蓝桥杯省模拟赛题目记录

题目集总目录 学习指路博客 堆与哈夫曼树与并查集

05-树 7 堆中的路径 (25 分)

本题链接

将在“小白专场”中介绍 C 语言的实现方法,是建立最小堆的基本操作训练,一定要做

题目大意

给出最小堆的插入序列,和下标序列,每个下标 i 输出 Data[i]到根结点路径上的值。

代码

#include <iostream>
using namespace std;
const int mindata = -10005;
const int maxsize = 10000;
typedef struct HeapStruct *MinHeap;
struct HeapStruct {
    int *Data;
    int Size;
};
MinHeap Create(int maxsize) {
    MinHeap H = new HeapStruct;
    H->Data = new int[maxsize];
    H->Size = 0;
    H->Data[0] = mindata;
    return H;
}
void Insert(int data, MinHeap H) {
    int i;
    i = ++H->Size;
    for(; H->Data[i>>1] > data; i >>= 1) {
        H->Data[i] = H->Data[i>>1];
    }
    H->Data[i] = data;
}
void PrintPath(int index, MinHeap H) {
    bool flag = false;
    while(index != 0) {
        if(flag) cout << " " << H->Data[index];
        else cout << H->Data[index];
        flag = true;
        index >>= 1;
    }
    cout << endl;
}
int main() {
    MinHeap H = Create(maxsize);
    int N, M, x;
    cin >> N >> M;
    for(int i = 0; i < N; ++i) {
        cin >> x;
        Insert(x, H);
    }
    for(int i = 0; i < M; ++i) {
        cin >> x;
        PrintPath(x, H);
    }
    return 0;
}

测试点

测试点如下 在这里插入图片描述

05-树 8 File Transfer (25 分)

本题链接

关于并查集,2005、2007 年浙江大学计算机学院免试研究生上机考试题即由此题改编而来。“小白专场”中介绍了原始并查集算法的优化,听完课以后自己尝试一下

题目大意

每个样例中,C 为查询任意两个计算机是否联通,I 为连通这两个计算机,最后 S 结束后检查是否全部连通,如没有全部不连通则输出有多少个连通的。

思路

并查集+路径压缩

代码

#include <iostream>
using namespace std;
const int maxn = 10005;
int fa[maxn];
int N, x, y;
char ch;
inline void init() {
    for(int i = 1; i <= N; ++i)
        fa[i] = i;
}
int find(int x) {//查询+路径压缩 把沿途的每个节点的父节点都设为根节点
    return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
void Merge(int x, int y) {
    fa[find(x)] = find(y);
}
int main() {
    scanf("%d", &N);
    init();
    getchar();
    scanf("%c", &ch);
    while(ch != 'S') {
        scanf("%d %d", &x, &y);
        getchar();
        if(ch == 'C') {
            if(find(x) == find(y)) cout << "yes" << endl;
            else cout << "no" << endl;
        } else if(ch == 'I') Merge(x, y);
        scanf("%c", &ch);
    }
    int ans = 0;
    for(int i = 1; i <= N; ++i) {
        if(fa[i] == i) ans++;
    }
    if(ans == 1) cout << "The network is connected." << endl;
    else cout << "There are " << ans << " components." << endl;
    return 0;
}

测试点

测试点如下 在这里插入图片描述

05-树 9 Huffman Codes (30 分)

本题链接

考察对 Huffman 编码的理解,程序可能略繁,量力而为。 题目大意: 给出若干字符及其频率,判断学生给的编码方式是否为最优编码

思路

看了陈越姥姥的讲解才知道,先根据给定的字符及其频率构建哈夫曼树,得到最优解的 WPL(编码长度),再判断学生给的编码,在长度一致的情况下,判断是否为前缀码。这里我用优先队列代替小顶堆的一大串代码,求 wpl 时用的是另一种方法。在这里插入图片描述 在这里插入图片描述

代码

#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
#define div 1000000007
const int maxn = 70;
const int inf  = 0x3f3f3f;
int N,M,codelen;
struct Code {
 char ch;
 string s;
 int f;//频率
}a[maxn];
typedef struct TreeNode* CodeTree;
struct TreeNode {
 int Weight;
 CodeTree Left, Right;
};
CodeTree head;
priority_queue<int,vector<int>, greater<int> > q; //优先队列代替小顶堆
int WPL() {
 int wpl = 0;
 while(q.size() > 1) {
  int t1 = q.top();
  q.pop();
  int t2 = q.top();
  q.pop();
  wpl += (t1+t2);
  q.push(t1+t2);
 }
 return wpl;
}
bool check() {//检查是否是前缀码
 head = new TreeNode;
 head->Left = head->Right = NULL;
 head->Weight = -1;
 CodeTree p = head;
 for (int i = 0; i < N; ++i) {
  string code = a[i].s;
  int len = code.length();
  for (int i = 0; i < len; ++i) {
   if (code[i] == '1') {
    if (!p->Right) {
     p->Right = new TreeNode;
     p->Right->Left = p->Right->Right = NULL;
     p->Right->Weight = -1;
    }
    p = p->Right;
    //中途有别的结点 有前缀码
   }
   else {
    if (!p->Left){
     p->Left = new TreeNode;
     p->Left->Right = p->Left->Left = NULL;
     p->Left->Weight = -1;
    }
    p = p->Left;
   }
   if (p->Weight != -1) return false;
  }
  p->Weight = 1;
  if (p->Left || p->Right) return false;
  p = head;
 }
 return true;
}
int main(){
    ios::sync_with_stdio(false);
    cin >> N;
    for(int i = 0; i < N; ++i) {
        cin >> a[i].ch >> a[i].f;
  q.push(a[i].f);
    }
 int codelen = WPL();
 cin >> M;
 while(M--) {
  int len = 0;
  for(int i = 0; i < N; ++i){
   cin >> a[i].ch >> a[i].s;
   len += a[i].f * a[i].s.length();
  }
  if(len == codelen && check()) cout << "Yes" << endl;
  else cout << "No" << endl;
 }
    return 0;
}

测试点

测试点如下 在这里插入图片描述

先使用 Remark42 作为临时评论系统,样式等有待优化

409k
35:31
184
使用字体寒蝉全圆体 · 感谢 字图 CDN 提供中文字体公益服务
© 2020 - 2025 cos @cosine
Powered by theme astro-koharu · Inspired by Shoka